/*
 * @Author: wuqingchun
 * @Date: 2024-10-22 19:26:23
 * @Description: 
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-10-29 19:50:48
 */
#include "libnet_error.h"
#include "net_event_select.h"

CNetEventSelect::CNetEventSelect()
{
    FD_ZERO(&m_stOriginReadSet);
    FD_ZERO(&m_stOriginWriteSet);
}


int32_t CNetEventSelect::Wait()
{
    m_stTmpReadSet = m_stOriginReadSet;
    m_stTmpWriteSet = m_stOriginWriteSet;

    int iMaxFdPlus1 = 0;
    if (!m_objConnectionMap.empty())
    {
        iMaxFdPlus1 = m_objConnectionMap.rbegin()->first + 1;
    }
    else
    {
        return ERROR_SUCCESS;
    }

    int iFdNum = select(iMaxFdPlus1, &m_stTmpReadSet, &m_stTmpWriteSet, nullptr, nullptr);
    if (iFdNum <= 0 && errno != EINTR)
    {
        return ERROR_FAILED;
    }

    int32_t iErr;
    
    printf("Wait result: %d\n", iFdNum);
    for (int iTmpFd = 0; iFdNum > 0 && iTmpFd < iMaxFdPlus1; iTmpFd++)
    {
        bool bHappen = false;

        if (FD_ISSET(iTmpFd, &m_stTmpReadSet))
        {
            bHappen = true;

            auto iter = m_objConnectionMap.find(iTmpFd);
            if (iter != m_objConnectionMap.end())
            {
                iErr = iter->second->DealRDEvent();
            }
        }

        if (FD_ISSET(iTmpFd, &m_stTmpWriteSet))
        {
            bHappen = true;
            auto iter = m_objConnectionMap.find(iTmpFd);
            if (iter != m_objConnectionMap.end())
            {
                iErr = iter->second->DealWREvent();
            }
        }

        if (bHappen)
        {
            iFdNum--;
        }
    }

    return ERROR_SUCCESS;
}


int32_t CNetEventSelect::AddRDEvent(INetTCPConnection* pobjConnection)
{
    if (pobjConnection == nullptr)
    {
        return ERROR_FAILED;
    }

    int iFd = pobjConnection->GetFd();
    m_objConnectionMap[iFd] = pobjConnection;
    FD_SET(iFd, &m_stOriginReadSet);

    printf("Add readable event, %d\n", iFd);

    return ERROR_SUCCESS;
}

int32_t CNetEventSelect::AddWREvent(INetTCPConnection* pobjConnection)
{
    if (pobjConnection == nullptr)
    {
        return ERROR_FAILED;
    }

    int iFd = pobjConnection->GetFd();
    m_objConnectionMap[iFd] = pobjConnection;
    FD_SET(iFd, &m_stOriginWriteSet);

    printf("Add writeable event, %d\n", iFd);

    return ERROR_SUCCESS;
}

void CNetEventSelect::DeleteRDEvent(INetTCPConnection* pobjConnection)
{
    if (pobjConnection == nullptr)
    {
        return;
    }
    
    int iFd = pobjConnection->GetFd();
    FD_CLR(iFd, &m_stOriginReadSet);

    if (!FD_ISSET(iFd, &m_stOriginWriteSet))
    {
        m_objConnectionMap.erase(iFd);
    }

    printf("Delete readable event, %d\n", iFd);
}

void CNetEventSelect::DeleteWREvent(INetTCPConnection* pobjConnection)
{
    if (pobjConnection == nullptr)
    {
        return;
    }

    int iFd = pobjConnection->GetFd();
    FD_CLR(iFd, &m_stOriginWriteSet);
    if (!FD_ISSET(iFd, &m_stOriginReadSet))
    {
        m_objConnectionMap.erase(iFd);
    }

    printf("Delete writeable event, %d\n", iFd);
}